# imports
import tornado.ioloop  # 核心IO循环模块
import tornado.httpserver  # 异步非阻塞HTTP服务器模块
from tornado.web import Application, RequestHandler
import json

from Server import router, logger, const
from Server.Utils import network, fileType
from Server.Handlers import basic


class FsApplication(Application):
    def __init__(self, **settings):
        super().__init__(**settings)
        if 'log' in self.settings:
            if self.settings['log']['en']:
                logger.logPath = self.settings['log']['path']
            logger.log2Console = self.settings['log']['con']

    def log_request(self, handler: RequestHandler) -> None:
        respStatusCode = handler.get_status()
        if respStatusCode < 400:
            logFunc = logger.info
        elif respStatusCode < 500:
            logFunc = logger.warning
        else:
            logFunc = logger.error

        req = handler.request
        requestTime = 1000.0 * req.request_time()
        headerName = self.settings['realIpHeader']
        if headerName not in req.headers.keys():
            realIP = req.remote_ip
        else:
            realIP = req.headers[headerName]

        details = ''
        if fileType.routeOrPathEquals(req.uri, const.UploadRoute):
            body = json.loads(req.body)
            routeFrom = body['rf']
            details += '"{0}{1}/{2}"[{3}/{4}]'.format(basic.Param.RoutePath[routeFrom], body['path'][len(routeFrom):],
                                                      body['filename'], body['seq'], body['total'])
        logFunc(
            "(%s) %.2fms %d %s %s %s" % (
                realIP,
                requestTime,
                respStatusCode,
                req.method,
                network.unquoteUrlCode(req.uri),
                details
            )
        )


def runServer(config: dict, onSuccess=None, onFail=None):
    router.initRouteTable(config)
    basic.initHandlerParam(config)
    app = FsApplication(handlers=router.table,
                        log=config['log'],
                        realIpHeader=config['server']['proxy']['real_ip_header'])

    try:
        app.listen(port=config['server']['port'],
                   address=config['server']['ip'])
    except OSError as e:
        if onFail is not None:
            onFail(str(e))
        return
    if onSuccess is not None:
        onSuccess()
    tornado.ioloop.IOLoop.instance().start()
